package io.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

@Slf4j
public class NIOServer {

    public static void main(String[] args) throws IOException {
        // 创建一个ServerSocketChannel，监听8888端口
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        // 绑定端口
        serverSocketChannel.socket().bind(new InetSocketAddress(8888));
        log.info("服务器启动成功，监听端口：{}", serverSocketChannel.socket().getLocalPort());

        Selector selector = Selector.open();
        // 将ServerSocketChannel注册到selector上
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 启动一个线程，执行多路复用程序
        new Thread(new SingleSelectorHandler(selector)).start();


    }

    static class SingleSelectorHandler implements Runnable {

        private final Selector selector;

        public SingleSelectorHandler(Selector selector) {
            this.selector = selector;
        }

        @Override
        public void run() {
            // 执行select多路复用程序
            while (true) {
                try {
                    // 阻塞等待就绪的Channel，这是关键点之一
                    selector.select();

                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        SelectionKey selectionKey = iterator.next();
                        // 删除本次已处理的key，防止下次select重复处理
                        iterator.remove();
                        // 处理请求
                        handleSelectKey(selectionKey);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void handleSelectKey(SelectionKey selectionKey) throws IOException {
            if (selectionKey.isValid()) {

                // 判断事件的类型来区别处理
                if (selectionKey.isAcceptable()) {
                    // 获取channel
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                    // 获取客户端连接
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    // 设置为非阻塞
                    socketChannel.configureBlocking(false);
                    // 注册到selector上
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }

                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    // 读取数据
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    socketChannel.read(buffer);
                    buffer.flip();
                    String msg = new String(buffer.array());
                    log.info("收到客户端消息：{}", msg);

                    // 回复客户端
                    ByteBuffer outBuffer = ByteBuffer.wrap("你好，客户端".getBytes());
                    socketChannel.write(outBuffer);
                }

            }


        }
    }

}
